package com.cnap.multiclouldmgmt.scheduleTask;


import com.cnap.multiclouldmgmt.controller.CnapClusterInfoController;
import com.cnap.multiclouldmgmt.model.vm.VmCreateModel;
import com.cnap.multiclouldmgmt.repository.master.VmCreateInfoMapper;
import com.cnap.multiclouldmgmt.service.CacheService;
import com.cnap.multiclouldmgmt.service.MicroSvcInfoService;
import com.cnap.multiclouldmgmt.service.VmResourceService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author dyq
 * 处理要
 */
@Configuration
@EnableScheduling
public class CreateVmScheduledTask {

    private final static Logger LOGGER = LoggerFactory.getLogger(CreateVmScheduledTask.class);

    @Autowired
    private VmCreateInfoMapper vmCreateInfoMapper;

    @Autowired
    private VmResourceService vmResourceService;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private MicroSvcInfoService microSvcInfoService;


    /**
     * 每一分钟处理一下vm创建
     * 如果cache中已经加锁。则不处理
     * 如果锁了很久，就重置
     * 然后开始多线程处理
     *      * 开通云资源，完成以下内容
     *      * 1.申请开通虚机，调用其他接口
     *      * 2.完成安全组开通，
     *      * 3.完成k8s等组件安装
     *      * 4、完成调度平台组件安装
     */
    @Scheduled(fixedDelay = 60*1000)
    public void createVmInfo() {

        try{

            //获取所有的要处理的事件（errormsg不为空的事件）
            //且wait_app_id为-1(-1表示刚写入，还没有做任何操作)
            List<VmCreateModel> vmCreateModels = vmCreateInfoMapper.getAllCreateInfo();

            //为空就下一步
            if ((vmCreateModels != null)&&(!vmCreateModels.isEmpty())) {
                Map<String, List<VmCreateModel>> waitVmCreateModelMap = new HashMap<>();
                //如果多个svc的要部署的cloudType+region+zone+arch+account，就吧其中一个置为等待，另一个执行
                for (VmCreateModel vmCreateModel : vmCreateModels) {

                    //如果createVm（说明不用创建机器）为空，那就直接把wait置为0，继续进行
                    if ((vmCreateModel.getVmModels() == null)||(vmCreateModel.getVmModels().isEmpty())){
                        vmCreateInfoMapper.updateVmWaitAppId(vmCreateModel.getSvcId(), "0");
                        continue;
                    }

                    String key = vmCreateModel.getVmModels().get(0).getCloudType()
                            + vmCreateModel.getVmModels().get(0).getRegionId()
                            + vmCreateModel.getVmModels().get(0).getZoneId()
                            + vmCreateModel.getVmModels().get(0).getArch()
                            + vmCreateModel.getVmModels().get(0).getAccountName()
                            + vmCreateModel.getUserName();
                    if (!waitVmCreateModelMap.containsKey(key)) {
                        waitVmCreateModelMap.put(key, new ArrayList<>());
                    }

                    waitVmCreateModelMap.get(key).add(vmCreateModel);
                }

                //list大于1的，都要做处理，第一个wait置为0，后面的wait置为第一个svcId
                for (String key : waitVmCreateModelMap.keySet()) {

                    String svcId = null;
                    for (VmCreateModel vmCreateModel : waitVmCreateModelMap.get(key)) {

                        if (StringUtils.isEmpty(svcId)) {
                            //如果这时候，没有其他的svc在同一个key下面建立集群，那就等第一个svc建完，其他才能建立
                            //如果已经有，svc在建立集群了，这个list里面的所有的svc都要等这个svc建完再说
                            VmCreateModel vmCreateModelInSameKeyBuliding =
                                    vmCreateInfoMapper.getVmCreateModelByCloudeTypeRegionZoneArchAccountNoEndNoError(
                                            vmCreateModel.getVmModels().get(0).getCloudType(),
                                            vmCreateModel.getVmModels().get(0).getRegionId(),
                                            vmCreateModel.getVmModels().get(0).getZoneId(),
                                            vmCreateModel.getArch(),
                                            vmCreateModel.getAccountName());

                            //保存wait为0,其他的都等这个建立完毕才能建
                            if (vmCreateModelInSameKeyBuliding != null) {
                                svcId = vmCreateModelInSameKeyBuliding.getSvcId();
                                vmCreateInfoMapper.updateVmWaitAppId(vmCreateModel.getSvcId(), svcId);
                            }else{
                                svcId = vmCreateModel.getSvcId();
                                vmCreateInfoMapper.updateVmWaitAppId(vmCreateModel.getSvcId(), "0");
                            }
                            continue;
                        }

                        //剩下的就都等这个完成再创建
                        vmCreateInfoMapper.updateVmWaitAppId(vmCreateModel.getSvcId(), svcId);
                    }
                }
            }

            //选择所有等待为0的去创建
            vmCreateModels = vmCreateInfoMapper.getAllCreateInfoWait0();
            if ((vmCreateModels == null)||(vmCreateModels.isEmpty())){
                return;
            }

            //异步的去执行
            for (VmCreateModel vmCreateModel : vmCreateModels){

                //如果errormsg不为空，就删除掉cache
                //且不处理
                if (StringUtils.isNotEmpty(vmCreateModel.getErrorMsg())){
                    cacheService.delVmCreate(vmCreateModel.getSvcId());
                    continue;
                }

                //放入cache中，防止冲突
                if (cacheService.getVmCreateTime(vmCreateModel.getSvcId()) < 0L) {
                    //记录本次处理的svc
                    LOGGER.info("CreateVmScheduledTask begin handl svcId={}",vmCreateModel.getSvcId());
                    //加线程锁
                    cacheService.putVmCreateSvc(vmCreateModel.getSvcId());
                    //多线程处理
                    vmResourceService.handleVmCreateInfo(vmCreateModel);
                }
            }

        }catch(Exception e){
          LOGGER.error("CreateVmScheduledTask create error",e);
        }
    }
}
